--- /dev/null
+/*
+ Enigma route and waypoint file format.
+ http://www.mglavionics.co.za/Docs/Enigma%20Waypoint%20format.pdf
+ Binary data are stored in little endian (Intel)
+
+ Copyright (C) 2009 Tobias Kretschmar, tobias.kretschmar@gmx.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+
+#define MYNAME "Enigma binary route and waypoint file format"
+
+#define WTYPE_WAYPOINT 0 // Waypoint of unspecified type
+#define WTYPE_AIRPORT 1 // Typical assignment for medium sized airports
+#define WTYPE_MAJORAIRPORT 2 // Typical assignment for large and international airports
+#define WTYPE_SEAPLANEBASE 3
+#define WTYPE_AIRFIELD 4 // Typical assignment for smaller municipal airfields, glider fields etc
+#define WTYPE_PRIVATEAIRFIELD 5
+#define WTYPE_ULTRALIGHTFIELD 6
+#define WTYPE_INTERSECTION 7 // (reporting point, boundary crossing)
+#define WTYPE_HELIPORT 8
+#define WTYPE_TACAN 9
+#define WTYPE_NDBDME 10
+#define WTYPE_NDB 11
+#define WTYPE_VORDME 12
+#define WTYPE_VORTAC 13
+#define WTYPE_FANMARKER 14
+#define WTYPE_VOR 15
+#define WTYPE_REPPT 16
+#define WTYPE_LFR 17
+#define WTYPE_UHFNDB 18
+#define WTYPE_MNDB 19
+#define WTYPE_MNDBDME 20
+#define WTYPE_LOM 21
+#define WTYPE_LMM 22
+#define WTYPE_LOCSDF 23
+#define WTYPE_MLSISMLS 24
+#define WTYPE_OTHERNAV 25 // Navaid not falling into any of the above types
+#define WTYPE_ALTITUDECHANGE 26 // Location at which altitude should be changed
+
+union wpt_data {
+ gbint32 wp_altitude; // Waypoint type 0-6,8: waypoint altitude in feet
+ gbint32 tg_altitude; // Waypoint type 26: target altitude in feet
+ gbuint32 frequency; // Waypoint type 9-25: freq in steps of 1000Hz (118Mhz = 180000)
+ gbint32 dummy; // waypoint type 7, unused
+};
+
+typedef struct enigma_wpt {
+ gbint32 latitude;
+ gbint32 longitude;
+ union wpt_data data;
+ gbuint8 waypoint_type;
+ gbuint8 shortname_len;
+ char shortname[6];
+ gbuint8 longname_len;
+ char longname[27];
+} ENIGMA_WPT;
+
+static gbfile *file_in, *file_out;
+
+static void
+rd_init(const char *fname)
+{
+ file_in = gbfopen_le(fname, "rb", MYNAME);
+}
+
+gbint32 decToEnigmaPosition (double val)
+{
+ int degrees = fabs(val);
+ double frac = fabs(val) - degrees;
+ int enigmadeg = degrees * 180000;
+ int enigmafrac = 180000 * frac;
+ int sign = (val < 0) ? -1 : +1;
+ return sign * (enigmadeg + enigmafrac);
+}
+
+float enigmaPositionToDec (gbint32 val)
+{
+ int deg = abs(val) / 180000;
+ int enigmafrac = abs(val) % 180000;
+ double frac = (double)enigmafrac / 180000;
+ int sign = (val < 0) ? -1 : +1;
+ return sign * (deg + frac);
+}
+
+static void
+data_read(void)
+{
+ struct enigma_wpt ewpt;
+ route_head *route = route_head_alloc();
+ route_add_head (route);
+
+ while (1 == gbfread(&ewpt, sizeof (ewpt), 1, file_in)) {
+ waypoint *wpt = waypt_new();
+ wpt->latitude = enigmaPositionToDec(le_read32(&ewpt.latitude));
+ wpt->longitude = enigmaPositionToDec(le_read32(&ewpt.longitude));
+ wpt->shortname = xstrndup(ewpt.shortname, ewpt.shortname_len);
+ wpt->description = xstrndup(ewpt.longname, ewpt.longname_len);
+ switch (ewpt.waypoint_type)
+ {
+ case WTYPE_WAYPOINT: // 0
+ case WTYPE_AIRPORT: // 1
+ case WTYPE_MAJORAIRPORT: // 2
+ case WTYPE_SEAPLANEBASE: // 3
+ case WTYPE_AIRFIELD: // 4
+ case WTYPE_PRIVATEAIRFIELD: // 5
+ case WTYPE_ULTRALIGHTFIELD: // 6
+ case WTYPE_HELIPORT: // 8
+ // waypoint altitude
+ wpt->altitude = FEET_TO_METERS(le_read32(&ewpt.data.wp_altitude) - 1000);
+ break;
+ case WTYPE_ALTITUDECHANGE: // 26
+ // target altitude
+ wpt->altitude = FEET_TO_METERS(le_read32(&ewpt.data.tg_altitude) - 1000);
+ break;
+ case WTYPE_INTERSECTION: // 7
+ // unused
+ break;
+ default:
+ // frequency
+ // wpt->frequency = wpt.le_readu32(ewpt.data.frequency);
+ ;
+ }
+ route_add_wpt(route, wpt);
+ }
+}
+
+static void
+rd_deinit(void)
+{
+ gbfclose(file_in);
+}
+
+static void
+wr_init(const char *fname)
+{
+ file_out = gbfopen_le(fname, "wb", MYNAME);
+}
+
+static void
+route_head_noop(const route_head *wp)
+{
+}
+
+#ifndef min
+#define min(a,b) ((a) < (b)) ? (a) : (b)
+#endif
+#ifndef max
+#define max(a,b) ((a) > (b)) ? (a) : (b)
+#endif
+
+static void
+enigma_waypt_disp(const waypoint *wpt)
+{
+ struct enigma_wpt ewpt;
+
+ memset (&ewpt, 0, sizeof (ewpt));
+
+ le_write32(&ewpt.latitude, decToEnigmaPosition(wpt->latitude));
+ le_write32(&ewpt.longitude, decToEnigmaPosition(wpt->longitude));
+ ewpt.waypoint_type = WTYPE_WAYPOINT;
+ if (wpt->altitude != unknown_alt)
+ le_write32(&ewpt.data.wp_altitude, METERS_TO_FEET(wpt->altitude) + 1000);
+ if (wpt->shortname != NULL)
+ {
+ ewpt.shortname_len = min (6, strlen (wpt->shortname));
+ strncpy(ewpt.shortname, wpt->shortname, 6);
+ }
+ if (wpt->description != NULL)
+ {
+ ewpt.longname_len = min (27, strlen (wpt->description));
+ strncpy(ewpt.longname, wpt->description, 27);
+ }
+ gbfwrite(&ewpt, sizeof (ewpt), 1, file_out);
+}
+
+static void
+data_write(void)
+{
+ route_disp_all(route_head_noop, route_head_noop, enigma_waypt_disp);
+}
+
+static void
+wr_deinit(void)
+{
+ gbfclose(file_in);
+}
+
+ff_vecs_t enigma_vecs = {
+ ff_type_file,
+ {
+ ff_cap_read | ff_cap_write, /* waypoints */
+ ff_cap_none, /* tracks */
+ ff_cap_read | ff_cap_write /* routes */
+ },
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ NULL,
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+};
--- /dev/null
+/*\r
+ PocketFMS waypoint text files (wpt).\r
+\r
+ Copyright (C) 2009 Tobias Kretschmar, tobias.kretschmar@gmx.de\r
+\r
+ This program is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with this program; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+ */\r
+\r
+#include "defs.h"\r
+#include "csv_util.h"\r
+\r
+#define MYNAME "PocketFMS waypoint text file format"\r
+\r
+static gbfile *file_in, *file_out;\r
+\r
+static void\r
+rd_init(const char *fname)\r
+{\r
+ file_in = gbfopen_le(fname, "r", MYNAME);\r
+}\r
+\r
+double wppos_to_dec(char *value)\r
+{\r
+ if (strstr(value, "°") == NULL)\r
+ return atof(value);\r
+ else \r
+ {\r
+ int degrees, minutes;\r
+ float seconds;\r
+ int sign = 1;\r
+\r
+ if (toupper(value[0]) == 'N' || toupper(value[0]) == 'E' || value[0] == '+')\r
+ {\r
+ value = &value[1];\r
+ }\r
+ else if (toupper(value[0]) == 'S' || toupper(value[0]) == 'W' || value[0] == '-')\r
+ {\r
+ value = &value[1];\r
+ sign = -1;\r
+ }\r
+\r
+ sscanf(value, "%d°%d'%f\"", °rees, &minutes, &seconds);\r
+ return sign * (degrees + ((float)minutes / 60) + (seconds / 3600));\r
+ }\r
+}\r
+\r
+static void\r
+data_read(void)\r
+{\r
+ char *buff;\r
+ int linecount = 0;\r
+ while ((buff = gbfgetstr(file_in))) {\r
+ char *s;\r
+ waypoint *wpt;\r
+ rtrim(buff);\r
+ if (strlen(buff) == 0)\r
+ break;\r
+ linecount++;\r
+ wpt = waypt_new();\r
+ s = buff;\r
+ s = csv_lineparse(s, "\\w", "", linecount);\r
+ wpt->shortname = xstrdup(s);\r
+ s = csv_lineparse(NULL, "\\w", "", linecount);\r
+ wpt->latitude = wppos_to_dec(s);\r
+ s = csv_lineparse(NULL, "\\w", "", linecount);\r
+ wpt->longitude = wppos_to_dec(s);\r
+ waypt_add(wpt);\r
+ }\r
+}\r
+\r
+static void\r
+rd_deinit(void)\r
+{\r
+ gbfclose(file_in);\r
+}\r
+\r
+static void\r
+wr_init(const char *fname)\r
+{\r
+ file_out = gbfopen_le(fname, "w", MYNAME);\r
+}\r
+\r
+static void\r
+enigma_waypt_disp(const waypoint *wpt)\r
+{\r
+ gbfprintf(file_out, "%s %f %f\n", wpt->shortname, wpt->latitude, wpt->longitude);\r
+}\r
+\r
+static void\r
+data_write(void)\r
+{\r
+ waypt_disp_all(enigma_waypt_disp);\r
+}\r
+\r
+static void\r
+wr_deinit(void)\r
+{\r
+ gbfclose(file_out);\r
+}\r
+\r
+ff_vecs_t pocketfms_wp_vecs = {\r
+ ff_type_file,\r
+ { \r
+ ff_cap_read | ff_cap_write, /* waypoints */\r
+ ff_cap_none, /* tracks */\r
+ ff_cap_none, /* routes */\r
+ },\r
+ rd_init,\r
+ wr_init,\r
+ rd_deinit,\r
+ wr_deinit,\r
+ data_read,\r
+ data_write,\r
+ NULL,\r
+ NULL,\r
+ CET_CHARSET_ASCII, 0 /* CET-REVIEW */\r
+};\r